using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Linq;
using Xeml.Sampling.Contracts;
using Xeml.SQLDataProviders;

namespace Xeml.Document
{
    /// <summary>
    /// Describes necessary information about a sample provider.
    /// </summary>
    public class DataProviderResource : INotifyPropertyChanged
    {
        #region Fields
        private string _friendlyName;
        public IDataProvider provider { get; private set; }
        private ComponentLoadState _compState = ComponentLoadState.Untouched;
        private string _uri;
        #endregion

        #region Properties
        /// <summary>
        /// The uri of the provider which will be loaded by the framework.
        /// </summary>
        public string Uri
        {
            get { return _uri; }
        }

        /// <summary>
        /// A friendly name for the ressource.
        /// </summary>
        public string FriendlyName
        {
            get
            {
                return this._friendlyName;
            }
            set
            {
                string oldVal = this._friendlyName;
                _friendlyName = value;
                if (oldVal != _friendlyName)
                {
                    OnPropertyChanged("FriendlyName");
                }

            }
        }

        /// <summary>
        /// The referenced validator component instance.
        /// </summary>
        public IDataProvider Provider
        {
            get
            {
                return this.provider;
            }
        }

        /// <summary>
        /// The current state of the referenced component.
        /// </summary>
        public ComponentLoadState ComponentState
        {
            get { return _compState; }
            set { _compState = value; }
        }

        #endregion

        #region Methods
        /// <summary>
        /// Loads the referenced component.
        /// </summary>
        public void LoadComponent(string uri)
        {
            _uri = uri;
            if (_compState != ComponentLoadState.Loaded)
            {
                try
                {
                    // TODO load a configured dp when appropriate
                    if (DataProviderManager.Instance.Contains(this._uri))
                    {
                        this.provider = DataProviderManager.Instance.CreateProvider(this._uri);
                        this._compState = ComponentLoadState.Loaded;
                    }
                    else
                        this._compState = ComponentLoadState.UnknownComponent;
                }
                catch (XemlComponentLoadFailedException)
                {
                    this._compState = ComponentLoadState.Failed;
                }
            }
        }
        #endregion

        private ProviderResourceCollection _collection;
        public ProviderResourceCollection Collection
        {
            get
            {
                return this._collection;
            }
            set
            {
                if (value != _collection)
                {

                    this._collection = value;
                }

            }
        }
        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string prop)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
            }
        }
        #endregion

        /// <summary>
        /// Load a and configures a DataProvider based on the configuration name
        /// </summary>
        /// <param name="uniqName">The configuration name</param>
        public void LoadConfiguredComponent(string uniqName)
        {
            DataProviderConfiguration config = SQLDataProviders.Configuration.GetConfiguration(uniqName);
            if (config != null)
            {
                _uri = config.Name; // TODO maybe autogenerate an uri based on the providerUri and the name of the configuration?
                LoadComponent(config.ProviderUri);
                if (this._compState == ComponentLoadState.Loaded)
                {
                    this.Provider.Configure(config);
                }
            }
            else
            { // ok, so no config was found, so load an unconfigured DataProvider
                if (SQLDataProviders.DataProviderManager.Instance.GetNameUriDict.Count > 0)
                {
                    String firstUri = SQLDataProviders.DataProviderManager.Instance.GetNameUriDict.Values.FirstOrDefault();
                    if (firstUri != null)
                    {
                        LoadComponent(firstUri);
                    }
                    else
                    {
                        this._compState = ComponentLoadState.Failed;
                    }
                }
            }
        }
    }
}
